// $codepro.audit.disable numericLiterals
/**
 * This class was created by Nick Popescu to be used in Space Trader
 */
import java.awt.EventQueue;
import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JSpinner;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.event.ActionListener;

import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeListener;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import javax.swing.SwingConstants;
import javax.swing.JPanel;

/**
 * This is the GUI for the Initial configuration Screen of the player. Allows
 * the player to select their name, to set up their skill points, and to select
 * the difficulty.
 * 
 * @author Nick Popescu
 * @version 1.0
 */

public class InitConfigScreen implements View {

    /**
     * this represents the JFrame used in the UI
     */
    private JFrame frame;

    /**
     * This represents the nameBox field for the user to enter in the name of
     * their character
     */
    private JTextField nameBox;

    /**
     * This represents the accept button
     */
    private JButton acceptBtn;

    /**
     * This represents the pilot skill point selector
     */
    private JSpinner pilotSpinner;

    /**
     * This represents the fighter skill point selector
     */
    private JSpinner fighterSpinner;

    /**
     * This represents the trader skill point selector
     */
    private JSpinner traderSpinner;

    /**
     * This represents the engineer skill point selector
     */
    private JSpinner engineerSpinner;

    /**
     * This represents the fighter skill point selector
     */
    private JLabel lblDifficulty;

    /**
     * This represents the default name of the player
     */
    private static final String DEFAULTNAME = "Enter Player Name";

    /**
     * the represents the JLabel that appears when the entered in name is
     * invalid
     */
    private JLabel invalidNameLabel;

    /**
     * This represents the JLabel that hold the number of skills remaining to be
     * assigned
     */
    private JLabel skillsRemainingLabel;

    /**
     * Launch the application.
     * 
     * @param args
     */
    public static void main(String[] args) {
	EventQueue.invokeLater(new Runnable() {
	    @Override
	    public void run() {
		try {
		    final InitConfigScreen window = new InitConfigScreen();
		    window.frame.setVisible(true);
		} catch (Exception e) {
		    e.printStackTrace();
		}
	    }
	});
    }

    /**
     * Create the application.
     */
    public InitConfigScreen() {
	initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
	frame = new JFrame("Space Trader");
	frame.getContentPane().setBackground(new Color(95, 158, 160));
	frame.setResizable(false);
	frame.setBounds(100, 100, 568, 408);
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.getContentPane().setLayout(null);

	final JLabel lblTitle = new JLabel("Configure Your Player");
	lblTitle.setForeground(new Color(255, 255, 255));
	lblTitle.setBounds(148, 10, 300, 30);
	lblTitle.setFont(new Font("Dialog", 1, 20));
	frame.getContentPane().add(lblTitle);

	final JLabel lblName = new JLabel("Name:");
	lblName.setForeground(new Color(255, 255, 255));
	lblName.setBounds(165, 55, 46, 14);
	frame.getContentPane().add(lblName);

	nameBox = new JTextField();
	nameBox.setText(DEFAULTNAME);
	nameBox.setBounds(220, 52, 140, 20);
	frame.getContentPane().add(nameBox);
	nameBox.setColumns(10);

	final JLabel lblNewLabel = new JLabel("Skills:");
	lblNewLabel.setForeground(new Color(255, 255, 255));
	lblNewLabel.setBounds(167, 80, 46, 14);
	frame.getContentPane().add(lblNewLabel);

	final JLabel lblPilot = new JLabel("Pilot");
	lblPilot.setForeground(new Color(255, 255, 255));
	lblPilot.setBounds(224, 106, 46, 14);
	frame.getContentPane().add(lblPilot);

	final JLabel lblFighter = new JLabel("Fighter");
	lblFighter.setForeground(new Color(255, 255, 255));
	lblFighter.setBounds(224, 137, 46, 14);
	frame.getContentPane().add(lblFighter);

	final JLabel lblTrader = new JLabel("Trader");
	lblTrader.setForeground(new Color(255, 255, 255));
	lblTrader.setBounds(224, 168, 57, 14);
	frame.getContentPane().add(lblTrader);

	final JLabel lblEngineer = new JLabel("Engineer");
	lblEngineer.setForeground(new Color(255, 255, 255));
	lblEngineer.setBounds(224, 199, 67, 14);
	frame.getContentPane().add(lblEngineer);

	pilotSpinner = new JSpinner();
	pilotSpinner.setModel(new SpinnerNumberModel(0, 0, 16, 1));
	pilotSpinner.setBounds(292, 106, 46, 20);
	frame.getContentPane().add(pilotSpinner);

	fighterSpinner = new JSpinner();
	fighterSpinner.setModel(new SpinnerNumberModel(0, 0, 16, 1));
	fighterSpinner.setBounds(292, 136, 46, 20);
	frame.getContentPane().add(fighterSpinner);

	traderSpinner = new JSpinner();
	traderSpinner.setModel(new SpinnerNumberModel(0, 0, 16, 1));
	traderSpinner.setBounds(292, 166, 46, 20);
	frame.getContentPane().add(traderSpinner);

	engineerSpinner = new JSpinner();
	engineerSpinner.setModel(new SpinnerNumberModel(0, 0, 16, 1));
	engineerSpinner.setBounds(292, 196, 46, 20);
	frame.getContentPane().add(engineerSpinner);

	acceptBtn = new JButton("Accept");
	acceptBtn.setBounds(236, 298, 89, 23);
	frame.getContentPane().add(acceptBtn);

	lblDifficulty = new JLabel("Difficulty:");
	lblDifficulty.setForeground(new Color(255, 255, 255));
	lblDifficulty.setBounds(140, 257, 77, 14);
	frame.getContentPane().add(lblDifficulty);

	final JComboBox comboBox = new JComboBox();
	comboBox.setModel(new DefaultComboBoxModel(new String[] { "Beginner",
		"Easy", "Medium", "Hard", "Impossible" }));
	comboBox.setBounds(219, 254, 124, 22);
	frame.getContentPane().add(comboBox);

	invalidNameLabel = new JLabel(
		"<HTML><u>Invalid name!</u><BR>Length should be<BR>between 3 and 13.</HTML>");
	invalidNameLabel.setForeground(new Color(255, 0, 0));
	invalidNameLabel.setVerticalAlignment(SwingConstants.TOP);
	invalidNameLabel.setBounds(374, 50, 206, 81);
	frame.getContentPane().add(invalidNameLabel);

	skillsRemainingLabel = new JLabel("Skill Points Left: 16");
	skillsRemainingLabel.setForeground(new Color(0, 255, 0));
	skillsRemainingLabel.setBounds(224, 81, 138, 14);
	frame.getContentPane().add(skillsRemainingLabel);
	invalidNameLabel.setVisible(false);
    }

    /**
     * Gets the name from the Name Box in the Character Creation menu.
     * 
     * @return Name from the Name Box.
     */

    @Override
    public String getName() {
	return nameBox.getText();
    }

    /**
     * Gets the number of the skill points that have been used up.
     * 
     * @return The number of skill points that have been used up.
     */

    @Override
    public int getSkillPoints() {
	return ((Integer) pilotSpinner.getValue()
		+ (Integer) fighterSpinner.getValue()
		+ (Integer) traderSpinner.getValue() + (Integer) engineerSpinner
		    .getValue());

    }

    /**
     * Places the skill point assignments into an array and returns it.
     * 
     * @return The array of all the skill point assignments.
     */

    @Override
    public int[] getSkillPointArray() {
	final int[] skillPointArray = new int[] {
		(Integer) pilotSpinner.getValue(),
		(Integer) fighterSpinner.getValue(),
		(Integer) traderSpinner.getValue(),
		(Integer) engineerSpinner.getValue() };
	return skillPointArray;
    }

    /**
     * Used by the Accept Button to see if it was clicked.
     * 
     * @param al
     *            The listener for the Accept Button.
     */

    @Override
    public void registerAccept(ActionListener al) {
	acceptBtn.addActionListener(al);

    }

    /**
     * Enables/disables the Accept Button in the Character Creation, based on
     * the flag.
     * 
     * @param flag
     *            True enables the button, False disables it.
     */

    @Override
    public void enableAccept(boolean flag) {
	acceptBtn.setEnabled(flag);

    }

    /**
     * Used to show the Initial Configuration Screen
     */

    @Override
    public void show() {
	frame.setVisible(true);

    }

    /**
     * Detects if the Spinners for the skills have been changed/updated with new
     * values.
     * 
     * @param cl
     *            The listener for the change.
     */

    @Override
    public void detectSkillChange(ChangeListener cl) {
	pilotSpinner.addChangeListener(cl);
	fighterSpinner.addChangeListener(cl);
	traderSpinner.addChangeListener(cl);
	engineerSpinner.addChangeListener(cl);
	// nameBox.addChangeListener(cl);

    }

    /**
     * Displays/Hides the Error message JLabel if the Name input is faulty.
     * 
     * @param flag
     *            True shows the error, false hides the message.
     */

    @Override
    public void displayNameError(boolean flag) {
	invalidNameLabel.setVisible(flag);
    }

    /**
     * Updates the JLabel for the number of the remaining skill points.
     * 
     * @param num
     *            The number of the remaining skill points.
     */

    @Override
    public void updateSkillsRemaining(int num) {
	skillsRemainingLabel.setText("Skill Points Left: " + num);
	if (num == 0) {
	    skillsRemainingLabel.setForeground(Color.YELLOW);
	} else {
	    skillsRemainingLabel.setForeground(Color.GREEN);
	}
    }

    /**
     * Gets the default text inside of the Name Box during character creation.
     * 
     * @return Default text inside of the Name Box.
     */

    @Override
    public String getDefaultName() {
	return DEFAULTNAME;
    }

    /**
     * Used to get all of the JSpinners (skill allocators) from the GUI.
     * 
     * @return An Array of all the skill JSpinners.
     */

    @Override
    public JSpinner[] getSpinners() {
	final JSpinner[] spinnerArray = new JSpinner[] { pilotSpinner,
		fighterSpinner, traderSpinner, engineerSpinner };
	return spinnerArray;
    }

    /**
     * Shows the passed-in JPanel, essentially moving the game to this Screen.
     * 
     * @param screen
     *            The JPanel that is to be displayed by the game's Frame.
     */
    @Override
    public void showScreen(JPanel screen) {
	final JPanel newScreen = screen;
	frame.getContentPane().setVisible(false);
	frame.setContentPane(newScreen);
	newScreen.setVisible(true);
	// frame.setVisible(false);
    }

    /**
     * Used to get the JFrame of this screen.
     * 
     * @return JFrame of this screen.
     */
    public JFrame getFrame() {
	return frame;
    }

    /**
     * This method returns a string representing the InitConfigScreen class
     * 
     * @return a String representing the InitConfigScreen class
     */
    @Override
    public String toString() {
	return this.toString();
    }
}
